import base64

import re
import rsa

from .endpoint import Endpoint
from .error import AuthError
from .util import *


class Auth:
    """
    用户登录鉴权相关
    """

    def __init__(self, objBiliapi, access_key='', cookie=None):
        self.access_key = access_key
        self.expires = -1
        self.cookie = cookie
        is_biliapi(objBiliapi)
        self._biliapi = objBiliapi
        if access_key != '':
            self.get_cookie([DOMAIN_BILI, DOMAIN_IM9])  # 获取cookie

    def login(self, usr, pwd):
        """
        登录B站并获得对应的登录凭据。此API不能返回URL。
        :param usr: 用户名/邮箱/手机号
        :param pwd: 密码
        :return:
        :author 天台
        """
        if self._biliapi.get_return_url():
            return None  # 此API不能返回URL
        # 获取access_key
        r = self._biliapi.request("http://passport.bilibili.com/login?act=getkey", sign=False)
        pwd_hash, key = r['hash'], rsa.PublicKey.load_pkcs1_openssl_pem(r['key'].encode("utf-8"))
        password = str(base64.urlsafe_b64encode(rsa.encrypt((pwd_hash + pwd).encode("utf-8"), key)))[2:-1]
        data = self._biliapi.request(ACCOUNT_HOST + "/login/v2?", {"userid": usr, "pwd": password})
        if data['code'] != 0:
            raise AuthError('Failed to login! Info: ' + data['message'])
        self.access_key = data['access_key']
        self.expires = data['expires']
        self.get_cookie([DOMAIN_BILI, DOMAIN_IM9])  # 获取cookie

    def get_detail(self):
        """
        获取当前登录凭据(access_key)的信息。
        :return:
        >>>{
        >>>    "mid": "2",                                   # 该用户的mid
        >>>    "appid": 878,                                 # 未知，似乎和ak、sk有关
        >>>    "access_key": "1234567890abcde1234567890abc", # 该用户的access_key
        >>>    "create_at": 1000000000,                      # 该access_key创建时间
        >>>    "userid": "bishi",                            # 该用户的id
        >>>    "uname": "碧诗",                              # 该用户的昵称
        >>>    "expires": 1000000000,                        # ak的有效期
        >>>    "permission": "ALL"                           # 普权，一般都是ALL，除非#(滑稽)
        >>>}
        """
        if self.access_key == '':
            raise AuthError("Haven't signed before!")
        data = self._biliapi.request(ACCOUNT_HOST + '/oauth', {'access_key': self.access_key}, sign=False)
        if self._biliapi.get_return_url():
            return data
        if data['code'] != 0:
            raise AuthError("Failed to login! Info: " + data['message'])
        return data['access_info']

    def get_cookie(self, domain=DOMAIN_BILI, override=False):
        """
        获取cookie。此API不能返回URL。
        :param override: 是否覆盖session原cookie。数组domain即为False
        :param domain: cookie域。DOMAIN_BILI、DOMAIN_IM9
        :return:
        """

        # 检查是否能返回URL
        if self._biliapi.get_return_url():
            return None  # 此API不能返回URL
        # 允许数组调用
        if isinstance(domain, list) or isinstance(domain, tuple):
            for d in domain:
                self.get_cookie(d, False)
            return

        @Endpoint(
            endpoint='http://passport%s/api/login/sso' % domain,
            params={'domain': domain},
            android=True,
            biliapi=self._biliapi
        )
        def request(access_key):
            pass

        if override:
            self._biliapi.get_session().cookies.clear()  # 清理原cookie
        request(self.access_key)  # 请求cookie
        cookie = self._biliapi.get_session().cookies
        if len(cookie) < 1:
            raise AuthError('Error in request cookie!')
        self.cookie = cookie

    @Endpoint(
        endpoint=ACCOUNT_HOST + '/login/renewToken',
        index='expires'
    )
    def refresh_ak(self, access_key):
        """
        将制指定ak有效期延期至1个月以后
        :param access_key:
        :return:
        """
        pass

    def get_captcha(self, domain=CAPTCHA_IM9):
        """
        获得captcha
        :param domain: captcha的域名
        :return:
        """
        if domain == CAPTCHA_IM9:
            url = 'http://www.im9.com/web/captcha.do'
        elif domain == CAPTCHA_BILI:
            url = 'http://www.bilibili.com/plus/widget/ajaxGetCaptchaKey.php?js'
        else:
            raise AuthError('Unknown domain.')

        @Endpoint(
            endpoint=url,
            sign=False,
            biliapi=self._biliapi
        )
        def request():
            pass

        data = request()
        captcha = re.search("'(.*?)'", data).group(1)
        return captcha
